﻿using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CoreCms.Net.Configuration;
using CoreCms.Net.IServices;
using CoreCms.Net.Loging;
using CoreCms.Net.Model.Entities;
using CoreCms.Net.Model.ViewModels.YiLianYun;
using CoreCms.Net.Utility.Helper;
using Flurl.Http;
using InitQ.Abstractions;
using InitQ.Attributes;
using Newtonsoft.Json;

namespace CoreCms.Net.RedisMQ
{
    public class OrderPrintSubscribe : IRedisSubscribe
    {
        private readonly ICoreCmsOrderItemServices _orderItemServices;
        private readonly ICoreCmsAreaServices _areaServices;
        private readonly ICoreCmsPrinterServices _coreCmsPrinterServices;


        public OrderPrintSubscribe(ICoreCmsOrderItemServices orderItemServices, ICoreCmsAreaServices areaServices, ICoreCmsPrinterServices coreCmsPrinterServices)
        {
            _orderItemServices = orderItemServices;
            _areaServices = areaServices;
            _coreCmsPrinterServices = coreCmsPrinterServices;
        }

        /// <summary>
        /// 订单打印队列
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        [Subscribe(RedisMessageQueueKey.OrderPrint)]
        private async Task OrderPrint(string msg)
        {
            try
            {
                var order = JsonConvert.DeserializeObject<CoreCmsOrder>(msg);
                if (order == null)
                {
                    NLogUtil.WriteAll(NLog.LogLevel.Info, LogType.RedisMessageQueue, "订单打印队列", "订单获取失败");
                    return;
                }
                CoreCmsPrinter model = null;
                if (order.storeId > 0)
                {
                    model = await _coreCmsPrinterServices.QueryByClauseAsync(p => p.storeId == order.storeId && p.isOpen == true, true, true);
                }
                model ??= await _coreCmsPrinterServices.QueryByClauseAsync(p => p.isDefault == true && p.isOpen == true, true, true);

                if (model == null)
                {
                    NLogUtil.WriteAll(NLog.LogLevel.Info, LogType.RedisMessageQueue, "订单打印队列", "打印机获取失败");
                    return;
                }

                var isNeedToken = false;
                if (string.IsNullOrEmpty(model.accessToken) || model.expiressEndTime == null)
                {
                    isNeedToken = true;
                }
                else
                {
                    //判断是否过期
                    var dt = DateTime.Now;
                    if (dt >= model.expiressEndTime)
                    {
                        var ts = dt - Convert.ToDateTime(model.expiressEndTime);
                        if (ts.Days > 35)
                        {
                            isNeedToken = true;
                        }
                        else
                        {
                            RefreshYiLianYunToken refreshToken = new RefreshYiLianYunToken
                            {
                                client_id = model.clientId,
                                grant_type = "client_credentials",
                                timestamp = CommonHelper.GetDateTimeStamp(DateTime.Now),
                                scope = "all",
                                id = Guid.NewGuid().ToString()
                            };
                            refreshToken.sign = CommonHelper.Md5For32((refreshToken.client_id + refreshToken.timestamp + model.clientSecret).ToLowerInvariant()).ToLowerInvariant();
                            var resultData = await YiLianYunConfig.AuthUrl.PostJsonAsync(refreshToken).ReceiveJson<YiLianYunAuthResult>();
                            //将获取到的数据存入数据库
                            if (resultData.error == "0")
                            {
                                model.accessToken = resultData.body.access_token;
                                model.refreshToken = resultData.body.refresh_token;
                                model.expiresIn = resultData.body.expires_in;
                                model.expiressEndTime = DateTime.Now.AddSeconds(resultData.body.expires_in);

                                await _coreCmsPrinterServices.UpdateAsync(
                                    p => new CoreCmsPrinter()
                                    {
                                        accessToken = resultData.body.access_token,
                                        refreshToken = resultData.body.refresh_token,
                                        expiresIn = resultData.body.expires_in,
                                        expiressEndTime = model.expiressEndTime,
                                        parameters = JsonConvert.SerializeObject(resultData.body)
                                    }, p => p.clientId == model.clientId && p.clientSecret == model.clientSecret, true);

                            }
                            else
                            {
                                NLogUtil.WriteAll(NLog.LogLevel.Info, LogType.RedisMessageQueue, "订单打印队列", "刷新AccessToken：" + resultData.error_description);
                                return;
                            }
                        }
                    }
                }

                if (isNeedToken)
                {
                    var getToken = new YiLianYunParam
                    {
                        client_id = model.clientId,
                        grant_type = "client_credentials",
                        timestamp = CommonHelper.GetDateTimeStamp(DateTime.Now),
                        scope = "all",
                        id = Guid.NewGuid().ToString()
                    };
                    getToken.sign = CommonHelper.Md5For32((getToken.client_id + getToken.timestamp + model.clientSecret).ToLowerInvariant()).ToLowerInvariant();

                    var resultData = await YiLianYunConfig.AuthUrl.PostJsonAsync(getToken).ReceiveJson<YiLianYunAuthResult>();
                    //将获取到的数据存入数据库
                    if (resultData.error == "0")
                    {
                        model.accessToken = resultData.body.access_token;
                        model.refreshToken = resultData.body.refresh_token;
                        model.expiresIn = resultData.body.expires_in;
                        model.expiressEndTime = DateTime.Now.AddSeconds(resultData.body.expires_in);

                        await _coreCmsPrinterServices.UpdateAsync(
                            p => new CoreCmsPrinter()
                            {
                                accessToken = resultData.body.access_token,
                                refreshToken = resultData.body.refresh_token,
                                expiresIn = resultData.body.expires_in,
                                expiressEndTime = model.expiressEndTime,
                                parameters = JsonConvert.SerializeObject(resultData.body)
                            }, p => p.clientId == model.clientId && p.clientSecret == model.clientSecret, true);

                    }
                    else
                    {
                        NLogUtil.WriteAll(NLog.LogLevel.Info, LogType.RedisMessageQueue, "订单打印队列", "获取AccessToken：" + resultData.error_description);
                        return;
                    }
                }

                //获取打印机是否在线
                var statusParam = new GetPrintStatusParam
                {
                    client_id = model.clientId,
                    access_token = model.accessToken,
                    machine_code = model.machineCode,
                    timestamp = CommonHelper.GetDateTimeStamp(DateTime.Now),
                    id = Guid.NewGuid().ToString()
                };
                statusParam.sign = CommonHelper.Md5For32((statusParam.client_id + statusParam.timestamp + model.clientSecret).ToLowerInvariant()).ToLowerInvariant();

                var getPrintStatusResult = await YiLianYunConfig.GetPrintStatusUrl.PostJsonAsync(statusParam).ReceiveJson<YiLianYunGetPrintStatusResult>();
                if (getPrintStatusResult.error != "0")
                {
                    NLogUtil.WriteAll(NLog.LogLevel.Info, LogType.RedisMessageQueue, "订单打印队列", "获取打印机在线状态：" + getPrintStatusResult.error_description);
                    return;
                }
                else
                {
                    switch (getPrintStatusResult.body.state)
                    {
                        case "0":
                            NLogUtil.WriteAll(NLog.LogLevel.Info, LogType.RedisMessageQueue, "订单打印队列", "获取打印机在线状态：机器未在线");
                            return;
                        case "2":
                            NLogUtil.WriteAll(NLog.LogLevel.Info, LogType.RedisMessageQueue, "订单打印队列", "机器缺纸");
                            return;
                    }

                    var payStr = EnumHelper.GetEnumDescriptionByKey<GlobalEnumVars.PaymentsTypes>(order.paymentCode);
                    var items = await _orderItemServices.QueryListByClauseAsync(p => p.orderId == order.orderId);
                    var areas = await _areaServices.GetAreaFullName(order.shipAreaId);
                    order.shipAreaName = areas.status ? areas.data + "" : "";

                    var receiptType = order.receiptType switch
                    {
                        (int)GlobalEnumVars.OrderReceiptType.IntraCityService => "同城配送",
                        (int)GlobalEnumVars.OrderReceiptType.Logistics => "物流快递",
                        (int)GlobalEnumVars.OrderReceiptType.SelfDelivery => "门店自提",
                        _ => string.Empty
                    };

                    var printStr = new StringBuilder();
                    printStr.Append("<center>--" + receiptType + "订单--</center>\r");
                    printStr.Append("................................\r");
                    printStr.Append("<center>--" + payStr + "--</center>\r");
                    printStr.Append("下单时间：" + order.createTime.ToString("yyyy-MM-dd HH:mm:ss") + "\r");
                    printStr.Append("订单编号：" + order.orderId + "\r");
                    printStr.Append("**************商品**************\r");
                    printStr.Append("<center>--购买明细--</center>\r");

                    if (items != null && items.Any())
                    {
                        foreach (var item in items)
                        {
                            printStr.Append(item.name + "*" + item.nums + "\r");
                        }
                    }
                    //printStr.Append("<center>--其他消费--</center>\r");
                    //printStr.Append("餐盒 1 2\r");
                    printStr.Append("................................\r");
                    printStr.Append("积分抵扣：￥" + order.pointMoney + "\r");
                    printStr.Append("订单优惠：￥" + order.orderDiscountAmount + "\r");
                    printStr.Append("商品优惠：￥" + order.goodsDiscountAmount + "\r");
                    printStr.Append("优惠券：￥" + order.couponDiscountAmount + "\r");
                    printStr.Append("总价：￥" + order.orderAmount + "\r");
                    printStr.Append("*******************************\r");
                    printStr.Append("区域：" + order.shipAreaName + "\r");
                    printStr.Append("地址：" + order.shipAddress + "\r");
                    printStr.Append("联系：" + order.shipName + " " + order.shipMobile + "\r");
                    printStr.Append("***************完结*************\r");

                    //小票打印
                    WordPrintRespone wordPrintRespone = new WordPrintRespone
                    {
                        client_id = model.clientId,
                        access_token = model.accessToken,
                        machine_code = model.machineCode,
                        content = printStr.ToString(),
                        origin_id = order.orderId,
                        timestamp = CommonHelper.GetDateTimeStamp(DateTime.Now)
                    };
                    wordPrintRespone.sign = CommonHelper
                        .Md5For32((wordPrintRespone.client_id + wordPrintRespone.timestamp + model.clientSecret)
                            .ToLowerInvariant()).ToLowerInvariant();
                    wordPrintRespone.id = Guid.NewGuid().ToString();

                    //打印文本：缺少参数！请检查参数信息！！或更改下请求头：Content-Type:application/x-www-form-urlencoded
                    var resultData = await YiLianYunConfig.PrintTextUrl
                        .WithHeader("Content-Type", "application/x-www-form-urlencoded")
                        .PostUrlEncodedAsync(wordPrintRespone).ReceiveJson<YiLianYunGetPrintTextResult>();
                    //当token返回失败时
                    if (resultData.error != "0")
                    {
                        NLogUtil.WriteAll(NLog.LogLevel.Info, LogType.RedisMessageQueue, "订单打印队列", "打印文本：" + resultData.error_description);
                    }
                    else
                    {
                        NLogUtil.WriteAll(NLog.LogLevel.Info, LogType.RedisMessageQueue, "订单打印队列", "打印文本：打印成功");
                    }
                }
            }
            catch (Exception ex)
            {
                NLogUtil.WriteAll(NLog.LogLevel.Error, LogType.RedisMessageQueue, "订单打印队列", msg, ex);
            }
            await Task.CompletedTask;
        }

    }
}
